#pragma once
#include <cassert>
#include <unordered_map>
#include <string>
#include <fstream>
#include <vector>
#include "../comm/Log.h"
#include "../comm/util.h"
using namespace std;

// Model:和数据进行交互(对题目数据进行管理)
namespace ns_model
{
    using namespace ns_log;
    using namespace ns_util;

    struct Question
    {
        Question() {}
        Question(string nub, string name, string level, int cpu_limit, int mem_limit)
        {
            _nub = nub;
            _name = name;
            _level = level;
            _cpu_limit = cpu_limit;
            _mem_limit = mem_limit;
        }

        string _nub;    // 题号
        string _name;   // 题目名称
        string _level;  // 题目难度
        int _cpu_limit; // 时间限制
        int _mem_limit; // 空间限制
        string _desc;   // 题目描述
        string _header; // 预留代码
        string _test;   // 测试用例
    };

    const string question_list = "./questions/questions.list";
    const string question_path = "./questions/";
    const string sep = " ";
    class Model
    {
        // 将question.list加载进unordered_map中
        bool LoadQuestions() // 初始化
        {
            // 1 地下城游戏 困难 1 25600

            ifstream in(question_list);
            if (!in.is_open())
            {
                LOG(FATAL) << "文件打开失败,检查是否存在题库文件" << endl;
                return false;
            }

            string line;
            while (getline(in, line))
            {
                vector<string> vs;
                str_util::SplitStr(line, &vs, sep);
                if (vs.size() != 5)
                {
                    LOG(WARNING) << "题库格式存在问题" << endl;
                    continue;
                }
                Question q(vs[0], vs[1], vs[2], stoi(vs[3]), stoi(vs[4]));

                string topic_path = question_path + q._nub;
                topic_path += "/";
                // 题目描述
                q._desc = file_util::ReadFile(topic_path + "desc.txt");
                // 预留代码
                q._header = file_util::ReadFile(topic_path + "header.cpp");
                // 测试用例
                q._test = file_util::ReadFile(topic_path + "test.cpp");

                _questions.insert({q._nub, q});
            }
            in.close();
            return true;
        }

    public:
        Model()
        {
            assert(LoadQuestions());
        }

        bool GetAllQuestions(vector<Question> *out)
        {
            if (_questions.empty())
            {
                LOG(DEBUG) << "没有录入任何题目" << endl;
                return false;
            }
            for (auto &p : _questions)
            {
                out->push_back(p.second);
            }
            return true;
        }

        bool GetOneQuestion(const string &nubs, Question *out)
        {
            if (!_questions.count(nubs))
            {
                LOG(DEBUG) << "该题号的题目不存在" << endl;
                return false;
            }
            *out = _questions[nubs];
            return true;
        }
        ~Model() {}

    private:
        unordered_map<string, Question> _questions;
    };
};